<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>class</title>
</head>
<body>
<script>
    class Person{
        constructor(name) {
            this.name = name
        }
        tell(){
            console.log(this.name)
        }

        static  getAge(){
            console.log(22)}
    }

    let person = new Person()
    /*
    * 构造函数创建出来的实例化对象访问的是原型中的方法 因此class中的方法和构造函数定义在原型中
    * */
    person.tell()

    console.dir(person)

    /*
    * 类可以直接访问的函数是静态函数  类如果想访问实例的方法要借用原型
    * */
    Person.getAge()
    Person.prototype.tell()

    console.log("----------------")

    /*
    *class中定义的函数是无法被枚举的
    * */
    for (const personKey in person) {
        console.log(personKey)
    }

    /*
    * 类表达式
    * */

    let animal = class {
        constructor(name) {
            this.name = name
        }
    }

    /*
    * 函数也可以返回一个class
    * */

    function  foo(){
        return class {
            constructor(name) {
                this.name = name
            }
        }
    }

    let res = foo()
    res = new res("ALice")


    /*
    * 类字段
    * */

    class  Men{

        /*
        * 如果实例对象的某个属性是不用从外部传值的话那么我们可以将其定义为class field
        * */
        gender = 'Men'

        /*
        * 如果实例对象的属性的赋值是由外部传入的话我们要将属性定义在构造函数中
        * */
        constructor(age) {
            this.age = age
            /*
            * 当前this是实例对象
            * 等号右边的this访问的是原型上的函数也就是95行定义的函数将 等号镞左边是动态在实例对象身上追加一个函数 本质是重写 因为实例身上有函数了所以就不会访问原型上的函数了
            *
            * */
            this.speak = this.speak.bind(this)
        }

        /*函数定义在硬原型上 如果将对象函数交给第三方调用时会因为动态this而报错*/
        // speak(){
        //     console.log(this.age)
        // }

        /*
        * 解决方法1:函数定义成class field形式那么每个对象身上抖音这个函数 而不是单独的一份定义在原型上
        *          其次将函数定义为箭头函数这样不管传递给谁进行调用this都会是men 因为箭头函数没有this会在定义的位置的外部作用域寻找this
        *          找的是函数作用域，因为class本质是一个函数，使用new 调用这个函数的本质就是类的实例对象在调用所以this是当前对象 静态this
        *
        *
        * 解决方法2:在当前this是当前实例对象的环境下(constructor)对函数进行bind 其实本质是在重写原型上的函数
        *
        * 解决方法3:也可以直接在要传递给第三方调用之前     men.speak = men.speak.bind(men)
        *
        * */
        speak = ()=>{
            console.log(this.age)
        }


    }

    let men =new Men(23)


    men.speak()
    let func = men.speak
    func()




</script>
</body>
</html>